package com.prj.ufdm.demo.tutorial.j2se.reflact;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * DESC: 反射测试 <br>
 * @author 胡义振
 * @date 2020年3月8日
 */
public class ReflactTest {
	
	public static void main(String[] args) throws Exception  {
		
		ReflactTest.getArrayTest(args);
	}
	
	
	// 数组反射
	private static void getArrayTest(String[] args) throws Exception {
		
		int [] i1 = new int[] {1,2};
		int [] i2 = new int[3];
		int [][] i3 = new int[3][2];
		String [] t1 = new String[] {"aa","bb"}; 
		
		// 同纬度，同类型数组字节码相等
		System.out.println("i1 与 i2 字节码是否相等："+(i1.getClass() == i2.getClass()));
		// 打印 i1 名称及父类名称
		System.out.println("\n i1 name："+i1.getClass().getName()); 
		// 父类为Object
		System.out.println("\n i1 父类："+i1.getClass().getSuperclass().getName());
		
		Object oi1 = i1;
		System.out.println("i1:"+i1);
		System.out.println("oi1:"+oi1);
		
		Object ot1 = t1;
		System.out.println("t1:"+t1);
		System.out.println("ot1:"+ot1);
		
		// 基本类型一维数组，不能转换为Object数组，因为 i1 装的是 int 是基本类型，不是 Object 类型
//		Object [] aoi1 = i1;
		
		Object [] aoi3 = i3;
		System.out.println("i3:"+i3);
		System.out.println("aoi3:"+aoi3);
		
		Object [] aot1 = t1;
		System.out.println("t1:"+t1);
		System.out.println("aot1:"+aot1);
		
		// 打印结果为数组(基本类型不转换)
		System.out.println("i1 as list:"+Arrays.asList(i1));
		// 打印结果为字符串(字符串数组转换为String，因为String是Object)
		System.out.println("t1 as list:"+Arrays.asList(t1));
		
		printObject(i1);

	}
	
	// 通过 Array 工具类实现数组反射
	private static void printObject(Object obj) {
		Class clazz = obj.getClass();
		if(clazz.isArray()) {
			int len = Array.getLength(obj);
			for(int i=0;i<len;i++) {
				System.out.println(Array.get(obj,i));
			}
		}
		else {
			System.out.println(obj);
		}
		
	}


	// 获取方法测试
	private static void getMethodTest(String[] args) throws Exception {
		ReflactUserService reflactUser = new ReflactUserService();
		Class clazz = ReflactUserService.class;
		// 调用普通方法
		Method method = clazz.getMethod("getUserDetail", String.class);
		String result = (String) method.invoke(reflactUser, "38");
		System.out.println("\n result:"+result);
		
		// 调用main方法
		Method mainMethod = clazz.getMethod("main", String[].class);
		String [] arrStr = new String [] { "参数1","参数12","参数13" };
		// 通过这种方式调用会出错（jvm不会把arrStr当做一个Object,会把当成三个参数，这里需要一个对象，所以报错）
		//mainMethod.invoke(null, arrStr);
		// 需要把 arrStr 封装成一个对象去调用
		mainMethod.invoke(null, (Object) arrStr);
	}
	
	// 得到构造方法测试
	private static void getConstructorTest() throws Exception {
		Class<ReflactUser> clazz = (Class<ReflactUser>) Class.forName("com.prj.ufdm.demo.tutorial.j2se.reflact.ReflactUser");
		Constructor<ReflactUser> constructor = clazz.getConstructor(String.class);
		ReflactUser reflactUser = (ReflactUser) constructor.newInstance("张三");
		System.out.println("\n reflactUser:"+reflactUser);
	}
	
	// 得到字段测试
	private static void getFieldTest() throws Exception {
		ReflactUser reflactUser = new ReflactUser("李四","25");
		
		Class clazz = reflactUser.getClass();
		// 获取 public 字段
		Field fieldName = clazz.getField("name");
		System.out.println("\n name:"+fieldName.get(reflactUser));
		// 获取 private 字段
		Field fielAge = clazz.getDeclaredField("age");
		fielAge.setAccessible(true);
		System.out.println("\n age:"+fielAge.get(reflactUser));
	}
	
	
}
